<?php
/*
 * description：
 * author：wh
 * email：
 * createTime：{2024/2/4} {16:59} 
 */

namespace wanghua\general_utility_tools_php\file;


use wanghua\general_utility_tools_php\tool\Tools;

/**
 * 文件、文件夹操作类
 *
 * eg：读取文件夹、复制文件等
 *
 * Class FileOperate
 * @package wanghua\general_utility_tools_php\file
 */
class File
{

    public $file_ext = '*.*';//扩展名
    public $unzip_path = '';//解压路径

    /**
     * desc：读取文件和文件夹
     *
     * author：wh
     * @param $folderPath 读取目标路径下的文件夹和文件
     *
     * @param $dirs 存储文件路径  eg:D:\wanghua\old_files
     *
    //array(3) {
    //  [0] => array(1) {
    //    ["path"] => string(25) "D:\wanghua\test_files/111"
    //  }
    //  [1] => array(1) {
    //    ["path"] => string(25) "D:\wanghua\test_files/222"
    //  }
    //}
     *
     *
     *
     *
     * @param $file_name_arr 存储文件路径、文件名称
     *
    //array(64) {
    //  [0] => array(3) {
    //    ["path"] => string(25) "D:\wanghua\test_files/111"
    //    ["path_file"] => string(33) "D:\wanghua\test_files/111/111.txt"
    //    ["filename"] => string(7) "111.txt"
    //  }
    //  [1] => array(3) {
    //    ["path"] => string(25) "D:\wanghua\test_files/111"
    //    ["path_file"] => string(37) "D:\wanghua\test_files/111/1111111.txt"
    //    ["filename"] => string(11) "1111111.txt"
    //  }
    //}
     */
    function read_folder($folderPath,&$dirs,&$file_name_arr) {
        // 获取指定目录下所有文件和文件夹
        $files = scandir($folderPath);
        foreach ($files as $file) {
            // 如果当前项为文件夹且不是"."或者".."
            if (is_dir("$folderPath/$file") && !in_array($file, array('.', '..'))) {
                $dirs[] = ['path'=>$folderPath.'/'.$file];//此时的$file是文件夹名称
                // 调用自身进行递归操作
                $this->read_folder("$folderPath/$file",$dirs,$file_name_arr);
            } elseif (!in_array($file, array('.', '..'))){ // 如果当前项为文件而非"."或者".."
                $file_name_arr[] = ['path'=>$folderPath,'path_file'=>"$folderPath/$file",'filename'=>$file];
            }
        }
    }

    /**
     * desc：复制文件
     *
     * author：wh
     * @param array $sourceFileArr 源文件路径数组 path,path_file,filename
     *
     * @param string $destination_path 目标存放路径 D:\wanghua\test_files\new_files
     *
     * @param array $cp_type_arr 允许复制的文件后缀 eg:['jpg','png,'spine']
     *
     * @param bool $is_cover 是否覆盖 默认false，不覆盖会以源文件名+微秒时间戳格式作为新的文件名
     *
     * @param bool $is_continue 相同文件是否跳过复制 默认 true
     *
     * 实战案例：
     *
    function testcopy(){
        $source_dir = 'D:\wanghua\test_files';//源文件路径
        $destination_path = 'D:\wanghua\test_files\new_files';//目标文件路径

        $dirs = [];//存储文件路径
        $file_name_arr = [];//含文件路径、名称
        $file_obj = new File();
        $file_obj->read_folder($source_dir,$dirs,$file_name_arr);
        //dump($dirs);
        //dump($file_name_arr);die;
        $file_obj->copy($file_name_arr,$destination_path,['jpg','png,'spine']);
    }
     *
     */
    function copy(array $sourceFileArr, string $destination_path, $cp_type_arr=['jpg','png'], $is_cover=false, $is_continue=false){
        //设置不超时
        set_time_limit(0);
        //源文件路径 => 目标文件路径
        foreach ($sourceFileArr as $key=>$file_arr){
            if(!file_exists($file_arr['path_file'])){
                continue;
            }
            //验证目标文件夹路径
            if(!file_exists($destination_path)){
                mkdir($destination_path,0777,true);
            }
            $name_arr = explode('.',$file_arr['filename']);
            //验证符合条件的文件类型
            if(!in_array($name_arr[1],$cp_type_arr)){
                continue;
            }
            if(file_exists($destination_path.'/'.$file_arr['filename'])){
                if($is_continue){
                    continue;//相同文件跳过复制
                }
                //覆盖
                if($is_cover){
                    copy($file_arr['path_file'], $destination_path.'/'.$file_arr['filename']);
                }else{
                    //不覆盖，名称区分
                    $microsecond = Tools::getMicrosecond();
                    copy($file_arr['path_file'], $destination_path.'/'.$name_arr[0].'('.$microsecond.').'.$name_arr[1]);
                }
            }else{
                copy($file_arr['path_file'], $destination_path.'/'.$file_arr['filename']);
            }
        }
    }

    /**
     * desc：递归删除目录
     *
     * $dir 物理路径
     *
     * author：wh
     */
    function recursive_delete($dir) {
        if (!is_dir($dir)) {
            return unlink($dir);
        }

        $handle = opendir($dir);
        while (($file = readdir($handle)) !== false) {
            if ($file === '.' || $file === '..') {
                continue;
            }
            $path = $dir . DIRECTORY_SEPARATOR . $file;
            if (is_dir($path)) {
                $this->recursive_delete($path);
            } else {
                unlink($path);
            }
        }
        closedir($handle);
        rmdir($dir);
    }


    /**
     * desc：解压ZIP文件并存储在本地
     * author：wh
     * @param resource $file_stream 文件流
     * 例如：$response = $client->request('POST', $url, [
                'headers' => $headers,
                'body' => $body,
            ]);
        // 处理响应
        //$file_stream =  $response->getBody();
     * @param string $save_path 存储路径
     * @return array
     * @throws \Exception
     */
    function unzip($file_stream,$save_path){
        $zpi_file_name = 'zip_tmp_file_'.Tools::rand_str(20).'.zip';
        //这个目录将会在结束时删除
        $zipTempPath = $save_path.'/tmp_zip_files/'; // 临时存放ZIP文件的路径
        //压缩文件保存目录
        if(!file_exists($zipTempPath)){
            mkdir($zipTempPath,0777,true);
        }
        $zpi_file = $zipTempPath.$zpi_file_name;
        // 保存ZIP文件到临时路径
        file_put_contents($zpi_file, $file_stream);

        $this->unzip_path = $zipTempPath.'unzip_files/';
        //解压目录
        if(!file_exists( $this->unzip_path)){
            mkdir( $this->unzip_path,0777,true);
        }
        // 解压ZIP文件
        $zip = new \ZipArchive();
        if ($zip->open($zpi_file) === TRUE) {
            $zip->extractTo( $this->unzip_path);//移动到临时解压目录
            $zip->close();
            //遍历所有文件(file_ext后缀自行指定)，遍历部分文件，如：*.json,*.zip,*.mp4,*.mp3等
            $wavFiles = $this->glob_by_ext( $this->unzip_path.$this->file_ext);

            //$urls = [];
            //// 遍历解压后的文件，生成URL
            //foreach ($wavFiles as $wavFilePath) {
            //    // 生成外部访问的URL
            //    $downloadUrl = request()->domain() . explode('public',$wavFilePath)[1];
            //    $urls[] = $downloadUrl;
            //}
            //// 返回所有WAV文件的URL
            //return ['wav_urls' => $urls];
            return $wavFiles;
        } else {
            throw new \Exception('Failed to open ZIP file.');
        }
    }

    /**
     * desc：获取指定扩展类型的文件列表
     *
     * author：wh
     * @param string $file_ext 如: wav,pm4,mp3,json,zip
     * @return array|false
     */
    function glob_by_ext($file_ext='*'){
        return glob( $this->unzip_path.'*.'.$file_ext);
    }
}